home *** CD-ROM | disk | FTP | other *** search
- #define LIBQBUILD_CORE
- #include "../include/libqbuild.h"
-
- int bitbytes; // (num_visleafs+63)>>3
- int bitlongs;
- int c_chains;
- int c_leafsee, c_portalsee;
- int c_portalskip, c_leafskip;
- int c_portaltest, c_portalpass, c_portalcheck;
- int c_vistest, c_mighttest;
- int count_sep;
- int leafon; // the next leaf to be given to a thread to process
- int originalvismapsize;
- int testvislevel = 2;
- int totalvis;
- unsigned char *uncompressed; // [bitbytes*num_visleafs]
- unsigned char portalsee[MAX_PORTALS];
-
- void CheckStack(register struct visleaf * leaf, register threaddata_t * thread)
- {
- pstack_t *p;
-
- for (p = thread->pstack_head.next; p; p = p->next)
- if (p->leaf == leaf)
- Error("CheckStack: leaf recursion");
- }
-
- /*
- * ==============
- * ClipToSeperators
- *
- * Source, pass, and target are an ordering of portals.
- *
- * Generates seperating planes canidates by taking two points from source and one
- * point from pass, and clips target by them.
- *
- * If target is totally clipped away, that portal can not be seen through.
- *
- * Normal clip keeps target on the same side as pass, which is correct if the
- * order goes source, pass, target. If the order goes pass, source, target then
- * flipclip should be set.
- * ==============
- */
- struct winding *ClipToSeperators(register struct winding * source, register struct winding * pass, register struct winding * target, register bool flipclip)
- {
- int i, j, k, l;
- struct plane plane;
- vec3_t v1, v2;
- float d;
- vec_t length;
- int counts[3];
- bool fliptest;
-
- // check all combinations
- for (i = 0; i < source->numpoints; i++) {
- l = (i + 1) % source->numpoints;
- VectorSubtract(source->points[l], source->points[i], v1);
-
- // fing a vertex of pass that makes a plane that puts all of the
- // vertexes of pass on the front side and all of the vertexes of
- // source on the back side
- for (j = 0; j < pass->numpoints; j++) {
- VectorSubtract(pass->points[j], source->points[i], v2);
-
- plane.normal[0] = v1[1] * v2[2] - v1[2] * v2[1];
- plane.normal[1] = v1[2] * v2[0] - v1[0] * v2[2];
- plane.normal[2] = v1[0] * v2[1] - v1[1] * v2[0];
-
- // if points don't make a valid plane, skip it
-
- length = plane.normal[0] * plane.normal[0]
- + plane.normal[1] * plane.normal[1]
- + plane.normal[2] * plane.normal[2];
-
- if (length < ON_EPSILON)
- continue;
-
- length = 1 / sqrt(length);
-
- plane.normal[0] *= length;
- plane.normal[1] *= length;
- plane.normal[2] *= length;
-
- plane.dist = DotProduct(pass->points[j], plane.normal);
-
- //
- // find out which side of the generated seperating plane has the
- // source portal
- //
- fliptest = FALSE;
- for (k = 0; k < source->numpoints; k++) {
- if (k == i || k == l)
- continue;
- d = DotProduct(source->points[k], plane.normal) - plane.dist;
- if (d < -ON_EPSILON) { // source is on the negative side, so we want all
- // pass and target on the positive side
-
- fliptest = FALSE;
- break;
- }
- else if (d > ON_EPSILON) { // source is on the positive side, so we want all
- // pass and target on the negative side
-
- fliptest = TRUE;
- break;
- }
- }
- if (k == source->numpoints)
- continue; // planar with source portal
-
- //
- // flip the normal if the source portal is backwards
- //
- if (fliptest) {
- VectorNegate(plane.normal);
- plane.dist = -plane.dist;
- }
-
- //
- // if all of the pass portal points are now on the positive side,
- // this is the seperating plane
- //
- counts[0] = counts[1] = counts[2] = 0;
- for (k = 0; k < pass->numpoints; k++) {
- if (k == j)
- continue;
- d = DotProduct(pass->points[k], plane.normal) - plane.dist;
- if (d < -ON_EPSILON)
- break;
- else if (d > ON_EPSILON)
- counts[0]++;
- else
- counts[2]++;
- }
- if (k != pass->numpoints)
- continue; // points on negative side, not a seperating plane
-
- if (!counts[0]) {
- continue; // planar with seperating plane
-
- }
-
- //
- // flip the normal if we want the back side
- //
- if (flipclip) {
- VectorNegate(plane.normal);
- plane.dist = -plane.dist;
- }
-
- //
- // clip target by the seperating plane
- //
- target = ClipWinding(target, &plane, FALSE);
- if (!target)
- return NULL; // target is not visible
-
- }
- }
-
- return target;
- }
-
- /*
- * ==================
- * RecursiveLeafFlow
- *
- * Flood fill through the leafs
- * If src_portal is NULL, this is the originating leaf
- * ==================
- */
- void RecursiveLeafFlow(register int leafnum, register threaddata_t * thread, register pstack_t * prevstack)
- {
- pstack_t stack;
- struct visportal *p;
- struct plane backplane;
- struct winding *source, *target;
- struct visleaf *leaf;
- int i, j;
- long *test, *might, *vis;
- bool more;
-
- c_chains++;
-
- leaf = leafs[leafnum];
- CheckStack(leaf, thread);
-
- // mark the leaf as visible
- if (!(thread->leafvis[leafnum >> 3] & (1 << (leafnum & 7)))) {
- thread->leafvis[leafnum >> 3] |= 1 << (leafnum & 7);
- thread->base->numcansee++;
- }
-
- prevstack->next = &stack;
- stack.next = NULL;
- stack.leaf = leaf;
- stack.portal = NULL;
- if(!(stack.mightsee = (unsigned char *)tmalloc(bitbytes)))
- Error("RecursiveLeafFlow: failed to allocate bitbytes!\n");
- might = (long *)stack.mightsee;
- vis = (long *)thread->leafvis;
-
- // check all portals for flowing into other leafs
- for (i = 0; i < leaf->numportals; i++) {
- p = leaf->portals[i];
-
- if (!(prevstack->mightsee[p->leaf >> 3] & (1 << (p->leaf & 7)))) {
- c_leafskip++;
- continue; // can't possibly see it
-
- }
-
- // if the portal can't see anything we haven't allready seen, skip it
- if (p->status == stat_done) {
- c_vistest++;
- test = (long *)p->visbits;
- }
- else {
- c_mighttest++;
- test = (long *)p->mightsee;
- }
- more = FALSE;
- for (j = 0; j < bitlongs; j++) {
- might[j] = ((long *)prevstack->mightsee)[j] & test[j];
- if (might[j] & ~vis[j])
- more = TRUE;
- }
-
- if (!more) { // can't see anything new
-
- c_portalskip++;
- continue;
- }
-
- // get plane of portal, point normal into the neighbor leaf
- stack.portalplane = p->plane;
- VectorNegateTo(p->plane.normal, backplane.normal);
- backplane.dist = -p->plane.dist;
-
- if (VectorCompare(prevstack->portalplane.normal, backplane.normal))
- continue; // can't go out a coplanar face
-
- c_portalcheck++;
-
- stack.portal = p;
- stack.next = NULL;
-
- target = ClipWinding(p->winding, &thread->pstack_head.portalplane, FALSE);
- if (!target)
- continue;
-
- if (!prevstack->pass) { // the second leaf can only be blocked if coplanar
-
- stack.source = prevstack->source;
- stack.pass = target;
- RecursiveLeafFlow(p->leaf, thread, &stack);
- FreeWinding(target);
- continue;
- }
-
- target = ClipWinding(target, &prevstack->portalplane, FALSE);
- if (!target)
- continue;
-
- source = CopyWinding(prevstack->source);
-
- source = ClipWinding(source, &backplane, FALSE);
- if (!source) {
- FreeWinding(target);
- continue;
- }
-
- c_portaltest++;
-
- if (testvislevel > 0) {
- target = ClipToSeperators(source, prevstack->pass, target, FALSE);
- if (!target) {
- FreeWinding(source);
- continue;
- }
- }
-
- if (testvislevel > 1) {
- target = ClipToSeperators(prevstack->pass, source, target, TRUE);
- if (!target) {
- FreeWinding(source);
- continue;
- }
- }
-
- if (testvislevel > 2) {
- source = ClipToSeperators(target, prevstack->pass, source, FALSE);
- if (!source) {
- FreeWinding(target);
- continue;
- }
- }
-
- if (testvislevel > 3) {
- source = ClipToSeperators(prevstack->pass, target, source, TRUE);
- if (!source) {
- FreeWinding(target);
- continue;
- }
- }
-
- stack.source = source;
- stack.pass = target;
-
- c_portalpass++;
-
- // flow through it for real
- RecursiveLeafFlow(p->leaf, thread, &stack);
-
- FreeWinding(source);
- FreeWinding(target);
- }
-
- tfree(stack.mightsee);
- }
-
- /*
- * ===============
- * PortalFlow
- *
- * ===============
- */
- void PortalFlow(register struct visportal * p)
- {
- threaddata_t data;
-
- if (p->status != stat_working)
- Error("PortalFlow: reflowed\n");
- p->status = stat_working;
-
- if(!(p->visbits = (unsigned char *)kmalloc(bitbytes)))
- Error("PortalFlow: failed to allocate bitbytes!\n");
-
- memset(&data, 0, sizeof(data));
- data.leafvis = p->visbits;
- data.base = p;
-
- data.pstack_head.portal = p;
- data.pstack_head.source = p->winding;
- data.pstack_head.portalplane = p->plane;
- data.pstack_head.mightsee = p->mightsee;
-
- RecursiveLeafFlow(p->leaf, &data, &data.pstack_head);
-
- p->status = stat_done;
- }
-
- /*
- * ===============================================================================
- *
- * This is a rough first-order aproximation that is used to trivially reject some
- * of the final calculations.
- *
- * ===============================================================================
- */
-
- void SimpleFlood(register struct visportal * srcportal, register int leafnum)
- {
- int i;
- struct visleaf *leaf;
- struct visportal *p;
-
- if (srcportal->mightsee[leafnum >> 3] & (1 << (leafnum & 7)))
- return;
- srcportal->mightsee[leafnum >> 3] |= (1 << (leafnum & 7));
- c_leafsee++;
-
- leaf = leafs[leafnum];
-
- for (i = 0; i < leaf->numportals; i++) {
- p = leaf->portals[i];
- if (!portalsee[p - portals])
- continue;
- SimpleFlood(srcportal, p->leaf);
- }
- }
-
- /*
- * ==============
- * BasePortalVis
- * ==============
- */
- void BasePortalVis(void)
- {
- int i, j, k;
- struct visportal *tp, *p;
- float d;
- struct winding *w;
-
- for (i = 0, p = portals; i < num_visportals * 2; i++, p++) {
- if(!(p->mightsee = (unsigned char *)kmalloc(bitbytes)))
- Error("BasePortalVis: failed to allocate bitbytes!\n");
- c_portalsee = 0;
- memset(portalsee, 0, num_visportals * 2);
-
- for (j = 0, tp = portals; j < num_visportals * 2; j++, tp++) {
- if (j == i)
- continue;
- w = tp->winding;
- for (k = 0; k < w->numpoints; k++) {
- d = DotProduct(w->points[k], p->plane.normal)
- - p->plane.dist;
- if (d > ON_EPSILON)
- break;
- }
- if (k == w->numpoints)
- continue; // no points on front
-
- w = p->winding;
- for (k = 0; k < w->numpoints; k++) {
- d = DotProduct(w->points[k], tp->plane.normal)
- - tp->plane.dist;
- if (d < -ON_EPSILON)
- break;
- }
- if (k == w->numpoints)
- continue; // no points on front
-
- portalsee[j] = 1;
- c_portalsee++;
-
- }
-
- c_leafsee = 0;
- SimpleFlood(p, p->leaf);
- p->nummightsee = c_leafsee;
- // printf ("portal:%4i c_leafsee:%4i \n", i, c_leafsee);
-
- }
- }
-
- /*
- *
- * Some textures (sky, water, slime, lava) are considered ambien sound emiters.
- * Find an aproximate distance to the nearest emiter of each class for each leaf.
- *
- */
-
- /*
- * ====================
- * SurfaceBBox
- *
- * ====================
- */
- void SurfaceBBox(__memBase, register struct dface_t * s, register vec3_t mins, register vec3_t maxs)
- {
- int i;
- short int j;
- int e;
- int vi;
- float *v;
-
- mins[0] = mins[1] = 999999;
- maxs[0] = maxs[1] = -99999;
-
- for (i = 0; i < s->numedges; i++) {
- e = bspMem->dsurfedges[s->firstedge + i];
- if (e >= 0)
- vi = bspMem->dedges[e].v[0];
- else
- vi = bspMem->dedges[-e].v[1];
- v = bspMem->dvertexes[vi].point;
-
- for (j = 0; j < 3; j++) {
- if (v[j] < mins[j])
- mins[j] = v[j];
- if (v[j] > maxs[j])
- maxs[j] = v[j];
- }
- }
- }
-
- /*
- * ====================
- * CalcAmbientSounds
- *
- * ====================
- */
- void CalcAmbientSounds(__memBase)
- {
- int i, j, k;
- short int l;
- struct dleaf_t *leaf, *hit;
- unsigned char *vis;
- struct dface_t *surf;
- vec3_t mins, maxs;
- float d, maxd;
- int ambient_type;
- struct texinfo *info;
- struct mipmap *miptex;
- int ofs;
- float dists[NUM_AMBIENTS];
- float vol;
-
- for (i = 0; i < num_visleafs; i++) {
- leaf = &bspMem->dleafs[i + 1];
-
- //
- // clear ambients
- //
- for (j = 0; j < NUM_AMBIENTS; j++)
- dists[j] = 1020;
-
- vis = &uncompressed[i * bitbytes];
-
- for (j = 0; j < num_visleafs; j++) {
- if (!(vis[j >> 3] & (1 << (j & 7))))
- continue;
-
- //
- // check this leaf for sound textures
- //
- hit = &bspMem->dleafs[j + 1];
-
- for (k = 0; k < hit->nummarksurfaces; k++) {
- surf = &bspMem->dfaces[bspMem->dmarksurfaces[hit->firstmarksurface + k]];
- info = &bspMem->texinfo[surf->texinfo];
- ofs = ((struct dmiptexlump_t *) bspMem->dtexdata)->dataofs[info->miptex];
- miptex = (struct mipmap *) (&bspMem->dtexdata[ofs]);
-
- if (!strncasecmp(miptex->name, "sky", 3))
- ambient_type = AMBIENT_SKY;
- else if (!strncasecmp(miptex->name, "*slime", 6))
- ambient_type = AMBIENT_SLIME; // AMBIENT_SLIME;
- else if (!strncasecmp(miptex->name, "*lava", 6))
- ambient_type = AMBIENT_LAVA;
- else if (miptex->name[0] == '*')
- ambient_type = AMBIENT_WATER;
- else
- continue;
-
- // find distance from source leaf to polygon
- SurfaceBBox(bspMem, surf, mins, maxs);
- maxd = 0;
- for (l = 0; l < 3; l++) {
- if (mins[l] > leaf->maxs[l])
- d = mins[l] - leaf->maxs[l];
- else if (maxs[l] < leaf->mins[l])
- d = leaf->mins[l] - mins[l];
- else
- d = 0;
- if (d > maxd)
- maxd = d;
- }
-
- maxd = 0.25;
- if (maxd < dists[ambient_type])
- dists[ambient_type] = maxd;
- }
- }
-
- for (j = 0; j < NUM_AMBIENTS; j++) {
- if (dists[j] < 100)
- vol = 1.0;
- else {
- vol = 1.0 - dists[2] * 0.002;
- if (vol < 0)
- vol = 0;
- }
- leaf->ambient_level[j] = vol * 255;
- }
- mprogress(num_visleafs, i + 1);
- }
- }
-
- //=============================================================================
-
- /*
- * =============
- * GetNextPortal
- *
- * Returns the next portal for a thread to work on
- * Returns the portals from the least complex, so the later ones can reuse
- * the earlier information.
- * =============
- */
- struct visportal *GetNextPortal(void)
- {
- int j;
- struct visportal *p, *tp;
- int min;
-
- min = 99999;
- p = NULL;
-
- for (j = 0, tp = portals; j < num_visportals * 2; j++, tp++) {
- if (tp->nummightsee < min && tp->status == stat_none) {
- min = tp->nummightsee;
- p = tp;
- }
- }
-
- if (p)
- p->status = stat_working;
-
- return p;
- }
-
- /*
- * ===============
- * CompressRow
- *
- * ===============
- */
- int CompressRow(register unsigned char * vis, register unsigned char * dest)
- {
- int j;
- int rep;
- int visrow;
- unsigned char *dest_p;
-
- dest_p = dest;
- visrow = (num_visleafs + 7) >> 3;
-
- for (j = 0; j < visrow; j++) {
- *dest_p++ = vis[j];
- if (vis[j])
- continue;
-
- rep = 1;
- for (j++; j < visrow; j++)
- if (vis[j] || rep == 255)
- break;
- else
- rep++;
- *dest_p++ = rep;
- j--;
- }
-
- return dest_p - dest;
- }
-
- /*
- * =============
- * SortPortals
- *
- * Sorts the portals from the least complex, so the later ones can reuse
- * the earlier information.
- * =============
- */
- int PComp(register struct visportal *a, register struct visportal *b)
- {
- if (a->nummightsee == b->nummightsee)
- return 0;
- if (a->nummightsee < b->nummightsee)
- return -1;
- return 1;
- }
-
- void SortPortals(void)
- {
- heapsort(portals, num_visportals * 2, sizeof(struct visportal), PComp);
- }
-
- /*
- * ===============
- * LeafFlow
- *
- * Builds the entire visibility list for a leaf
- * ===============
- */
- void LeafFlow(__memBase, register int leafnum)
- {
- struct visleaf *leaf;
- unsigned char *outbuffer;
- unsigned char compressed[MAX_MAP_LEAFS / 8];
- int i, j;
- int numvis;
- struct visportal *p;
-
- //
- // flow through all portals, collecting visible bits
- //
- outbuffer = uncompressed + leafnum * bitbytes;
- leaf = leafs[leafnum];
- for (i = 0; i < leaf->numportals; i++) {
- p = leaf->portals[i];
- if (p->status != stat_done)
- Error("portal not done\n");
- for (j = 0; j < bitbytes; j++)
- outbuffer[j] |= p->visbits[j];
- }
-
- if (outbuffer[leafnum >> 3] & (1 << (leafnum & 7)))
- Error("Leaf portals saw into leaf\n");
-
- outbuffer[leafnum >> 3] |= (1 << (leafnum & 7));
-
- numvis = 0;
- for (i = 0; i < num_visleafs; i++)
- if (outbuffer[i >> 3] & (1 << (i & 3)))
- numvis++;
-
- //
- // compress the bit string
- //
- if (bspMem->visOptions & VIS_VERBOSE)
- mprintf("----- leaf %4i ---------\n%5i visible\n", leafnum, numvis);
- totalvis += numvis;
-
- i = CompressRow(outbuffer, compressed);
-
- if ((bspMem->visdatasize + i) > bspMem->max_visdatasize)
- ExpandClusters(bspMem, LUMP_VISIBILITY);
- memcpy(bspMem->dvisdata + bspMem->visdatasize, compressed, i);
- bspMem->dleafs[leafnum + 1].visofs = bspMem->visdatasize; // leaf 0 is a common solid
- bspMem->visdatasize += i;
- }
-
- /*
- * ==================
- * CalcPortalVis
- * ==================
- */
- void CalcPortalVis(__memBase)
- {
- int i;
- struct visportal *p;
-
- // fastvis just uses mightsee for a very loose bound
- if (bspMem->visOptions & VIS_FAST) {
- for (i = 0; i < num_visportals * 2; i++) {
- portals[i].visbits = portals[i].mightsee;
- portals[i].status = stat_done;
- }
- return;
- }
-
- leafon = 0;
-
- while((p = GetNextPortal())) {
- PortalFlow(p);
- if (bspMem->visOptions & VIS_VERBOSE)
- mprintf("----- portal %4i -------\n %5i mightsee\n%5i cansee\n", (int)(p - portals), p->nummightsee, p->numcansee);
- }
-
- if (bspMem->visOptions & VIS_VERBOSE) {
- mprintf("%5i portalcheck\n%5i portaltest\n%5i portalpass\n", c_portalcheck, c_portaltest, c_portalpass);
- mprintf("%5i c_vistest\n%5i c_mighttest\n", c_vistest, c_mighttest);
- }
-
- }
-
- /*
- * ==================
- * CalcVis
- * ==================
- */
- void CalcVis(__memBase)
- {
- int i;
-
- BasePortalVis();
- //SortPortals();
- CalcPortalVis(bspMem);
-
- //
- // assemble the leaf vis lists by oring and compressing the portal lists
- //
- for (i = 0; i < num_visleafs; i++) {
- LeafFlow(bspMem, i);
- mprogress(num_visleafs, i + 1);
- }
-
- mprintf("%5i average leafs visible\n", totalvis / num_visleafs);
- }
-
- /*
- * ==============================================================================
- *
- * PASSAGE CALCULATION (not used yet...)
- *
- * ==============================================================================
- */
-
- bool PlaneCompare(register struct plane * p1, register struct plane * p2)
- {
- int i;
-
- if (fabs(p1->dist - p2->dist) > 0.01)
- return FALSE;
-
- for (i = 0; i < 3; i++)
- if (fabs(p1->normal[i] - p2->normal[i]) > 0.001)
- return FALSE;
-
- return TRUE;
- }
-
- struct seperatingplane *Findpassages(register struct winding * source, register struct winding * pass)
- {
- int i, j, k, l;
- struct plane plane;
- vec3_t v1, v2;
- float d;
- double length;
- int counts[3];
- bool fliptest;
- struct seperatingplane *sep, *list;
-
- list = NULL;
-
- // check all combinations
- for (i = 0; i < source->numpoints; i++) {
- l = (i + 1) % source->numpoints;
- VectorSubtract(source->points[l], source->points[i], v1);
-
- // fing a vertex of pass that makes a plane that puts all of the
- // vertexes of pass on the front side and all of the vertexes of
- // source on the back side
- for (j = 0; j < pass->numpoints; j++) {
- VectorSubtract(pass->points[j], source->points[i], v2);
-
- plane.normal[0] = v1[1] * v2[2] - v1[2] * v2[1];
- plane.normal[1] = v1[2] * v2[0] - v1[0] * v2[2];
- plane.normal[2] = v1[0] * v2[1] - v1[1] * v2[0];
-
- // if points don't make a valid plane, skip it
-
- length = plane.normal[0] * plane.normal[0]
- + plane.normal[1] * plane.normal[1]
- + plane.normal[2] * plane.normal[2];
-
- if (length < ON_EPSILON)
- continue;
-
- length = 1 / sqrt(length);
-
- plane.normal[0] *= length;
- plane.normal[1] *= length;
- plane.normal[2] *= length;
-
- plane.dist = DotProduct(pass->points[j], plane.normal);
-
- //
- // find out which side of the generated seperating plane has the
- // source portal
- //
- fliptest = FALSE;
- for (k = 0; k < source->numpoints; k++) {
- if (k == i || k == l)
- continue;
- d = DotProduct(source->points[k], plane.normal) - plane.dist;
- if (d < -ON_EPSILON) { // source is on the negative side, so we want all
- // pass and target on the positive side
-
- fliptest = FALSE;
- break;
- }
- else if (d > ON_EPSILON) { // source is on the positive side, so we want all
- // pass and target on the negative side
-
- fliptest = TRUE;
- break;
- }
- }
- if (k == source->numpoints)
- continue; // planar with source portal
-
- //
- // flip the normal if the source portal is backwards
- //
- if (fliptest) {
- VectorNegate(plane.normal);
- plane.dist = -plane.dist;
- }
-
- //
- // if all of the pass portal points are now on the positive side,
- // this is the seperating plane
- //
- counts[0] = counts[1] = counts[2] = 0;
- for (k = 0; k < pass->numpoints; k++) {
- if (k == j)
- continue;
- d = DotProduct(pass->points[k], plane.normal) - plane.dist;
- if (d < -ON_EPSILON)
- break;
- else if (d > ON_EPSILON)
- counts[0]++;
- else
- counts[2]++;
- }
- if (k != pass->numpoints)
- continue; // points on negative side, not a seperating plane
-
- if (!counts[0])
- continue; // planar with pass portal
-
- //
- // save this out
- //
- count_sep++;
-
- if(!(sep = (struct seperatingplane *)kmalloc(sizeof(struct seperatingplane))))
- Error("FindPassages: failed to allocate seperating plane!\n");
- sep->next = list;
- list = sep;
- sep->plane = plane;
- }
- }
-
- return list;
- }
-
- /*
- * ============
- * CalcPassages
- * ============
- */
- void CalcPassages(void)
- {
- int i, j, k;
- int count, count2;
- struct visleaf *l;
- struct visportal *p1, *p2;
- struct seperatingplane *sep;
- struct passage *passages;
-
- mprintf(" - building passages...\n");
-
- count = count2 = 0;
- for (i = 0; i < num_visleafs; i++) {
- l = leafs[i];
-
- for (j = 0; j < l->numportals; j++) {
- p1 = l->portals[j];
- for (k = 0; k < l->numportals; k++) {
- if (k == j)
- continue;
-
- count++;
- p2 = l->portals[k];
-
- // definately can't see into a coplanar portal
- if (PlaneCompare(&p1->plane, &p2->plane))
- continue;
-
- count2++;
-
- sep = Findpassages(p1->winding, p2->winding);
- if (!sep) {
- // Error ("No seperating planes found in portal pair");
- count_sep++;
- if(!(sep = (struct seperatingplane *)kmalloc(sizeof(struct seperatingplane))))
- Error("CalcPassages: failed to allocate seperate plane!\n");
- sep->next = NULL;
- sep->plane = p1->plane;
- }
- if(!(passages = (struct passage *)kmalloc(sizeof(struct passage))))
- Error("CalcPassages: failed to allocate passage!\n");
- passages->planes = sep;
- passages->from = p1->leaf;
- passages->to = p2->leaf;
- passages->next = l->passages;
- l->passages = passages;
- }
- }
- }
-
- mprintf("%5i numpassages (%i)\n", count2, count);
- mprintf("%5i total passages\n", count_sep);
- }
-
- //=============================================================================
-
- bool vis(__memBase, int level, char *prtBuf)
- {
- int i;
-
- mprintf("----- Vis ---------------\n");
-
- AllocClusters(bspMem, LUMP_VISIBILITY);
-
- if(!(bspMem->visOptions & VIS_MEM))
- LoadPortals(prtBuf);
- if(level)
- testvislevel = level;
-
- originalvismapsize = num_visportals * ((num_visportals + 7) / 8);
- bitbytes = ((num_visportals + 63) & ~63) >> 3;
- bitlongs = bitbytes / sizeof(long);
-
- if(!(uncompressed = (char *)kmalloc(bitbytes * num_visleafs)))
- Error("Vis: failed to allocate bitbytes!\n");
-
- mprintf("----- CalcVis -----------\n");
- //CalcPassages ();
- CalcVis(bspMem);
-
- mprintf("%5i c_chains\n", c_chains);
- mprintf("%5i visdatasize (compressed from %i)\n", bspMem->visdatasize, originalvismapsize);
-
- mprintf("----- CalcAmbientSounds -\n");
- CalcAmbientSounds(bspMem);
-
- for(i = 0; i < num_visleafs; i++)
- if(leafs[i])
- FreeLeaf(leafs[i]);
- for(i = 0; i < (num_visportals * 2); i++)
- if(portals[i].winding);
- FreeWinding(portals[i].winding);
- tfree(leafs);
- tfree(portals);
- kfree();
-
- return TRUE;
- }
-
-